package com.virus.server.utils;

import com.virus.server.http.ContextSession;
import com.virus.server.http.Request;
import com.virus.server.http.Response;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.*;

public class SessionUtils {

    private static Map<String, ContextSession> sessionMap = new HashMap<>();

    private static Integer defaultTimOut = getDefaultTimeOut();

    static {
        validateSession();
    }

    private static void validateSession() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    Set<String> jsessionids = sessionMap.keySet();
                    List<String> expiredSessionIds = new ArrayList<>();
                    for (String jsessionid : jsessionids) {
                        ContextSession session = sessionMap.get(jsessionid);
                        long interval = System.currentTimeMillis() - session.getLastAccessedTime();
                        if (interval > session.getMaxInactiveInterval() * 1000) {
                            expiredSessionIds.add(jsessionid);
                        }
                    }
                    for (String expiredSessionId : expiredSessionIds) {
                        sessionMap.remove(expiredSessionId);
                    }
                    try {
                        Thread.sleep(20 * 1000);
                        System.out.println("-------");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    private static Integer getDefaultTimeOut() {

        int defaultTimeOut = 30;
        String webxml = null;
        try {
            webxml = FileUtils.readUTF8(Constant.webXml);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (webxml == null) {
            return null;
        }
        Document document = Jsoup.parse(webxml);
        Elements elements = document.select("session-config session-timeout");
        if (elements.isEmpty()) {
            return defaultTimeOut;
        }
        return Integer.parseInt(elements.first().text());
    }

    public static HttpSession getSession(String jsessionid, Request request, Response response) {
        if (jsessionid == null || jsessionid.isEmpty()) {
            return createNewSession(request, response);
        } else {
            ContextSession session = sessionMap.get(jsessionid);
            if (session == null) {
                return createNewSession(request, response);
            }
            session.setLastAccessedTime(System.currentTimeMillis());
            return session;
        }
    }

    private static void sendJSESSIONIDByCookie(HttpSession session, Response response) {
        Cookie cookie = new Cookie("JSESSIONID", session.getId());
        response.addCookie(cookie);
    }

    private static HttpSession createNewSession(Request request, Response response) {

        ServletContext servletContext = request.getServletContext();
        String id = generateSESSIONID();
        ContextSession session = new ContextSession(id, servletContext);
        session.setMaxInactiveInterval(defaultTimOut);
        sessionMap.put(id, session);
        sendJSESSIONIDByCookie(session, response);
        return session;
    }

    private static synchronized String generateSESSIONID() {
        return SecurityUtils.toMD5(UUID.randomUUID().toString());
    }
}
